import del from 'del';
import path from 'path';
import gulp from 'gulp';
import _debug from 'debug';
import config from './config';
import browserSync from 'browser-sync';
import sequence from 'gulp-sequence';
import lodash from 'lodash';
import { argv } from 'yargs';


var fs = require('hexo-fs');
var chalk = require('chalk');
var swig = require('swig');
var moment = require('moment');
var spawn = require('./deploy/spawn');


var swigHelpers = {
    now: function(format) {
        return moment().format(format);
    }
};


require('./gulp/assets');
require('./gulp/styles');
require('./gulp/html');
require('./gulp/js');

gulp.config = {};

const { __DEV__ } = config.globals;

let browserInstace;

const log = _debug('app:core');

gulp.task('clean', (next) => {
	del.sync([config.dist_root, config.tmp_root]);
	next();
});

gulp.task('compile', (next) => {
	sequence(['js', 'styles', 'assets'], 'html')(next);
});

gulp.task('serve', ['watch'], (next) => {
	browserInstace = browserSync.init({
		port: config.server_port,
		startPath: config.server_index,
		server: {
			baseDir: config.dist_root,
		},
		// reloadDelay: 1000,
		notify: false
	});

	next();
});

gulp.task('watch', (next) => {
	gulp.watch(path.join(config.src_js, '**/*'), ['watch:js']);
	gulp.watch(path.join(config.src_styles, '**/*'), ['watch:styles']);
	gulp.watch(path.join(config.src_html, '**/*'), ['watch:html']);
	gulp.watch(path.join(config.src_assets, '**/*'), ['watch:assets']);
	next();
});

const reload = next => {
	if (browserInstace) {
		log('server reloading');
		browserInstace.reload();
	}
	if (next) next();
};

let scope;
if (__DEV__ && argv.scope) {
	scope = argv.scope.split(',');
}

gulp.task('watch:js', next => {
	if (scope) {
		const srcs = gulp.config.src_js = [];

		for (const s of scope) {
			srcs.push(path.join(config.src_js, `${s}/**/*.main.js`));
		}
	}

	sequence('js', () => {
		reload(next);
	});
});

gulp.task('watch:styles', next => {
	if (scope) {
		gulp.config.src_styles = [path.join(config.src_styles, '**/*.main.less')];

		for (const s of config.scopes) {
			if (!lodash.includes(scope, s)) {
				gulp.config.src_styles.push(`!${path.join(config.src_styles, `${s}/**/*.main.less`)}`);
			}
		}
	}

	sequence('styles', () => {
		reload(next);
	});
});

gulp.task('watch:html', ['html'], reload);

gulp.task('watch:assets', ['assets'], reload);

gulp.task('gitdeploy', ()=>{
    pushGithub();
});

var pushGithub = function(args) {

	var deploy_dir = path.join(__dirname, 'deploy_git');
	var dist_dir = path.join(__dirname, 'dist');

	var message = commitMessage(args);
	var verbose = true;

	if (!config.deploy.repository) {
		var help = '';

		help += 'You have to configure the deployment settings in  config/index.js first!\n\n';
		help += 'Example:\n';
		help += '  deploy:\n';
		help += '    repository: https://github.com/zhongqiang1839/zhongqiang1839.github.io.git\n';
		help += '    repo: <repository url>\n';
		help += '    branch: [master]\n';
		help += '    message: [message]\n\n';

		console.log(help);
		return;
	}

	function git() {


		var len = arguments.length;
		var args = new Array(len);

		for (var i = 0; i < len; i++) {
			args[i] = arguments[i];
		}

		return spawn('git', args, {
			cwd: deploy_dir,
			verbose: verbose
		});

	}

	function setup() {
		var userName = config.deploy.branch;
		var userEmail = config.deploy.email;

		// Create a placeholder for the first commit
		return fs.writeFile(path.join(deploy_dir, 'placeholder'), '').then(function() {
			return git('init');
		}).then(function() {
			return userName && git('config', 'user.name', userName);
		}).then(function() {
			return userEmail && git('config', 'user.email', userEmail);
		}).then(function() {
			return git('add', '-A');
		}).then(function() {
			return git('commit', '-m', 'First commit');
		});
	}

	function push(repo) {
		return git('add', '-A').then(function() {
			return git('commit', '-m', message).catch(function() {
				// Do nothing. It's OK if nothing to commit.
			});
		}).then(function() {
			return git('push', '-u', repo.url, 'HEAD:' + repo.branch, '--force');
		});
	}

	return fs.exists(deploy_dir).then(function(exist) {
		if (exist) return;

		console.log('Setting up Git deployment...');
		return setup();
	}).then(function() {
		console.log('Clearing .deploy_git folder...');
		return fs.emptyDir(deploy_dir);
	}).then(function() {
		console.log('Copying files from public folder...');
		return fs.copyDir(dist_dir, deploy_dir);
	}).then(function() {
		return [{
			url: config.deploy.repository,
			branch: config.deploy.branch
		}];
	}).each(function(repo) {
		return push(repo);
	});
};

function commitMessage() {
	var message = 'Site updated: {{ now(\'YYYY-MM-DD HH:mm:ss\') }}';
	return swig.compile(message)(swigHelpers);
}

